From 0603254247671c416109940b56e6a5766fd403f5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 3 Oct 2005 15:02:23 +0100 Subject: [PATCH] Do not pickle vcpu state on save/restore. We can construct suitable initial state for each vcpu during restore, without need for pickle/unpickle. Signed-off-by: Keir Fraser --- .../arch/xen/i386/kernel/process.c | 7 ++ .../arch/xen/i386/kernel/smpboot.c | 96 ++++++++----------- .../arch/xen/i386/kernel/traps.c | 6 ++ linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 25 +---- .../arch/xen/x86_64/kernel/smpboot.c | 13 +-- .../arch/xen/x86_64/kernel/traps.c | 6 ++ 6 files changed, 63 insertions(+), 90 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c index d75dcd67a9..38940bbea6 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c @@ -141,6 +141,13 @@ static inline void play_dead(void) } #endif /* CONFIG_HOTPLUG_CPU */ +void cpu_restore(void) +{ + play_dead(); + local_irq_enable(); + cpu_idle(); +} + /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c index dba898d0c3..7fe4d8da07 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c @@ -802,7 +802,6 @@ static int __init do_boot_cpu(int apicid) extern void hypervisor_callback(void); extern void failsafe_callback(void); extern void smp_trap_init(trap_info_t *); - int i; cpu = ++cpucount; /* @@ -853,12 +852,6 @@ static int __init do_boot_cpu(int apicid) /* FPU is set up to default initial state. */ memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt.trap_ctxt[i].vector = i; - ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS; - } smp_trap_init(ctxt.trap_ctxt); /* No LDT. */ @@ -1585,61 +1578,48 @@ void smp_resume(void) local_setup_timer_irq(); } -static atomic_t vcpus_rebooting; - -static void restore_vcpu_ready(void) +void vcpu_prepare(int vcpu) { + extern void hypervisor_callback(void); + extern void failsafe_callback(void); + extern void smp_trap_init(trap_info_t *); + extern void cpu_restore(void); + vcpu_guest_context_t ctxt; + struct task_struct *idle = idle_task(vcpu); - atomic_dec(&vcpus_rebooting); -} + if (vcpu == 0) + return; -void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ - int r; - int gdt_pages; - r = HYPERVISOR_vcpu_pickle(vcpu, ctxt); - if (r != 0) - panic("pickling vcpu %d -> %d!\n", vcpu, r); - - /* Translate from machine to physical addresses where necessary, - so that they can be translated to our new machine address space - after resume. libxc is responsible for doing this to vcpu0, - but we do it to the others. */ - gdt_pages = (ctxt->gdt_ents + 511) / 512; - ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]); - for (r = 0; r < gdt_pages; r++) - ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]); -} + memset(&ctxt, 0, sizeof(ctxt)); -int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ - int r; - int gdt_pages = (ctxt->gdt_ents + 511) / 512; - - /* This is kind of a hack, and implicitly relies on the fact that - the vcpu stops in a place where all of the call clobbered - registers are already dead. */ - ctxt->user_regs.esp -= 4; - ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip; - ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready; - - /* De-canonicalise. libxc handles this for vcpu 0, but we need - to do it for the other vcpus. */ - ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]); - for (r = 0; r < gdt_pages; r++) - ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]); - - atomic_set(&vcpus_rebooting, 1); - r = HYPERVISOR_boot_vcpu(vcpu, ctxt); - if (r != 0) { - printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r); - return -1; - } + ctxt.user_regs.ds = __USER_DS; + ctxt.user_regs.es = __USER_DS; + ctxt.user_regs.fs = 0; + ctxt.user_regs.gs = 0; + ctxt.user_regs.ss = __KERNEL_DS; + ctxt.user_regs.cs = __KERNEL_CS; + ctxt.user_regs.eip = (unsigned long)cpu_restore; + ctxt.user_regs.esp = idle->thread.esp; + ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1; - /* Make sure we wait for the new vcpu to come up before trying to do - anything with it or starting the next one. */ - while (atomic_read(&vcpus_rebooting)) - barrier(); + memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); - return 0; + smp_trap_init(ctxt.trap_ctxt); + + ctxt.ldt_ents = 0; + + ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address); + ctxt.gdt_ents = cpu_gdt_descr[vcpu].size / 8; + + ctxt.kernel_ss = __KERNEL_DS; + ctxt.kernel_sp = idle->thread.esp0; + + ctxt.event_callback_cs = __KERNEL_CS; + ctxt.event_callback_eip = (unsigned long)hypervisor_callback; + ctxt.failsafe_callback_cs = __KERNEL_CS; + ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; + + ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT; + + (void)HYPERVISOR_boot_vcpu(vcpu, &ctxt); } diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c index 323e7409c9..81f701b8a4 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c @@ -1012,6 +1012,12 @@ void __init trap_init(void) void smp_trap_init(trap_info_t *trap_ctxt) { trap_info_t *t = trap_table; + int i; + + for (i = 0; i < 256; i++) { + trap_ctxt[i].vector = i; + trap_ctxt[i].cs = FLAT_KERNEL_CS; + } for (t = trap_table; t->address; t++) { trap_ctxt[t->vector].flags = t->flags; diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 5a093f6795..59fc5f0b78 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -74,11 +74,8 @@ static int __do_suspend(void *ignore) extern unsigned long *pfn_to_mfn_frame_list[]; #ifdef CONFIG_SMP - static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; - cpumask_t prev_online_cpus, prev_present_cpus; - - void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); - int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); + cpumask_t prev_online_cpus; + int vcpu_prepare(int vcpu); #endif extern void xencons_resume(void); @@ -132,16 +129,6 @@ static int __do_suspend(void *ignore) preempt_enable(); -#ifdef CONFIG_SMP - cpus_clear(prev_present_cpus); - for_each_present_cpu(i) { - if (i == 0) - continue; - save_vcpu_context(i, &suspended_cpu_records[i]); - cpu_set(i, prev_present_cpus); - } -#endif - gnttab_suspend(); #ifdef __i386__ @@ -189,11 +176,6 @@ static int __do_suspend(void *ignore) time_resume(); -#ifdef CONFIG_SMP - for_each_cpu_mask(i, prev_present_cpus) - restore_vcpu_context(i, &suspended_cpu_records[i]); -#endif - __sti(); xencons_resume(); @@ -201,6 +183,9 @@ static int __do_suspend(void *ignore) xenbus_resume(); #ifdef CONFIG_SMP + for_each_present_cpu(i) + vcpu_prepare(i); + out_reenable_cpus: for_each_cpu_mask(i, prev_online_cpus) { j = cpu_up(i); diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c index ee0ebd51c8..a48b7aa469 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c @@ -742,12 +742,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) /* FPU is set up to default initial state. */ memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt.trap_ctxt[i].vector = i; - ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS; - } smp_trap_init(ctxt.trap_ctxt); /* No LDT. */ @@ -1267,13 +1261,8 @@ void smp_resume(void) local_setup_timer_irq(); } -void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ -} - -int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +void vcpu_prepare(int vcpu) { - return 0; } #endif diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c index 9008537635..fc4defe342 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c @@ -956,6 +956,12 @@ void __init trap_init(void) void smp_trap_init(trap_info_t *trap_ctxt) { trap_info_t *t = trap_table; + int i; + + for (i = 0; i < 256; i++) { + trap_ctxt[i].vector = i; + trap_ctxt[i].cs = FLAT_KERNEL_CS; + } for (t = trap_table; t->address; t++) { trap_ctxt[t->vector].flags = t->flags; -- 2.30.2